#ifndef _EXCEPTION_H_
#define _EXCEPTION_H_

#include "Object.h"

#define THROW_EXCEPTION(Type, msg) (throw Type(msg, __FILE__, __LINE__))

namespace MySTL
{

class Exception : public Object
{
public:
	Exception(const char* message);
	Exception(const char* location, int line);
	Exception(const char* message, const char* location, int line);
	Exception(const Exception& obj);
	Exception& operator =(const Exception& obj);

	const char* message() const;
	const char* location() const;

	~Exception();

protected:
	void init(const char* message, const char* location, int line);
	void init(const char* message, const char* location);

protected:
	char* m_message;
	char* m_location;
};

class NoEnoughMemoryException : public Exception
{
public:
	NoEnoughMemoryException(const char* message) : Exception(message) {}
	NoEnoughMemoryException(const char* location, int line) : Exception(location, line) {}
	NoEnoughMemoryException(const char* message, const char* location, int line) : Exception(message, location, line) {}
	NoEnoughMemoryException(const Exception& obj) : Exception(obj) {}
};

class IndexOutOfBoundsException : public Exception
{
public:
	IndexOutOfBoundsException(const char* message) : Exception(message) {}
	IndexOutOfBoundsException(const char* location, int line) : Exception(location, line) {}
	IndexOutOfBoundsException(const char* message, const char* location, int line) : Exception(message, location, line) {}
	IndexOutOfBoundsException(const Exception& obj) : Exception(obj) {}
};

class ParameterErrorException : public Exception
{
public:
	ParameterErrorException(const char* message) : Exception(message) {}
	ParameterErrorException(const char* location, int line) : Exception(location, line) {}
	ParameterErrorException(const char* message, const char* location, int line) : Exception(message, location, line) {}
	ParameterErrorException(const Exception& obj) : Exception(obj) {}
};

class InvalidOperationException : public Exception
{
public:
	InvalidOperationException(const char* message) : Exception(message) {}
	InvalidOperationException(const char* location, int line) : Exception(location, line) {}
	InvalidOperationException(const char* message, const char* location, int line) : Exception(message, location, line) {}
	InvalidOperationException(const Exception& obj) : Exception(obj) {}
};

class NullPointerException : public Exception
{
public:
	NullPointerException(const char* message) : Exception(message) {}
	NullPointerException(const char* location, int line) : Exception(location, line) {}
	NullPointerException(const char* message, const char* location, int line) : Exception(message, location, line) {}
	NullPointerException(const Exception& obj) : Exception(obj) {}
};

}

#endif